<template>
	<view :id="attrs.id" :class="'_'+name+' '+attrs.class" :style="attrs.style">
		<block v-for="(n, i) in childs" v-bind:key="i">
			<!-- 图片 -->
			<!-- 占位图 -->
			<image v-if="n.name==='img'&&((opts[1]&&!ctrl[i])||ctrl[i]<0)" class="_img" :style="n.attrs.style"
				:src="ctrl[i]<0?opts[2]:opts[1]" mode="widthFix" />
			<!-- 显示图片 -->
			<!-- #ifdef H5 || APP-PLUS -->
			<img v-if="n.name==='img'" :id="n.attrs.id" :class="'_img '+n.attrs.class"
				:style="(ctrl[i]===-1?'display:none;':'')+n.attrs.style"
				:src="n.attrs.src||(ctrl.load?n.attrs['data-src']:'')" :data-i="i" @load="imgLoad" @error="mediaError"
				@tap.stop="imgTap" @longpress="imgLongTap" />
			<!-- #endif -->
			<!-- #ifndef H5 || APP-PLUS -->
			<image v-if="n.name==='img'" :id="n.attrs.id" :class="'_img '+n.attrs.class"
				:style="(ctrl[i]===-1?'display:none;':'')+'width:'+(ctrl[i]||1)+'px;height:1px;'+n.attrs.style"
				:src="n.attrs.src" :mode="n.h?'':'widthFix'" :lazy-load="opts[0]" :webp="n.webp"
				:show-menu-by-longpress="opts[3]&&!n.attrs.ignore" :image-menu-prevent="!opts[3]||n.attrs.ignore"
				:data-i="i" @load="imgLoad" @error="mediaError" @tap.stop="imgTap" @longpress="imgLongTap" />
			<!-- #endif -->
			<!-- 文本 -->
			<!-- #ifndef MP-BAIDU || MP-ALIPAY || MP-TOUTIAO -->
			<text v-else-if="n.text" :user-select="n.us" decode>{{n.text}}</text>
			<!-- #endif -->
			<text v-else-if="n.name==='br'">\n</text>
			<!-- 链接 -->
			<view v-else-if="n.name==='a'" :id="n.attrs.id" :class="(n.attrs.href?'_a ':'')+n.attrs.class"
				hover-class="_hover" :style="'display:inline;'+n.attrs.style" :data-i="i" @tap.stop="linkTap">
				<node name="span" :childs="n.children" :opts="opts" style="display:inherit" />
			</view>
			<!-- 视频 -->
			<!-- #ifdef APP-PLUS -->
			<view v-else-if="n.html" :id="n.attrs.id" :class="'_video '+n.attrs.class" :style="n.attrs.style"
				v-html="n.html" />
			<!-- #endif -->
			<!-- #ifndef APP-PLUS -->
			<video v-else-if="n.name==='video'" :id="n.attrs.id" :class="n.attrs.class" :style="n.attrs.style"
				:autoplay="n.attrs.autoplay" :controls="n.attrs.controls" :loop="n.attrs.loop" :muted="n.attrs.muted"
				:poster="n.attrs.poster" :src="n.src[ctrl[i]||0]" :data-i="i" @play="play" @error="mediaError" />
			<!-- #endif -->
			<!-- #ifdef H5 || APP-PLUS -->
			<iframe v-else-if="n.name==='iframe'" :style="n.attrs.style" :allowfullscreen="n.attrs.allowfullscreen"
				:frameborder="n.attrs.frameborder" :src="n.attrs.src" />
			<embed v-else-if="n.name==='embed'" :style="n.attrs.style" :src="n.attrs.src" />
			<!-- #endif -->
			<!-- #ifndef MP-TOUTIAO -->
			<!-- 音频 -->

			<!-- #endif -->
			<view v-else-if="(n.name==='table'&&n.c)||n.name==='li'" :id="n.attrs.id"
				:class="'_'+n.name+' '+n.attrs.class" :style="n.attrs.style">
				<node v-if="n.name==='li'" :childs="n.children" :opts="opts" />
				<view v-else v-for="(tbody, x) in n.children" v-bind:key="x"
					:class="'_'+tbody.name+' '+tbody.attrs.class" :style="tbody.attrs.style">
					<node v-if="tbody.name==='td'||tbody.name==='th'" :childs="tbody.children" :opts="opts" />
					<block v-else v-for="(tr, y) in tbody.children" v-bind:key="y">
						<view v-if="tr.name==='td'||tr.name==='th'" :class="'_'+tr.name+' '+tr.attrs.class"
							:style="tr.attrs.style">
							<node :childs="tr.children" :opts="opts" />
						</view>
						<view v-else :class="'_'+tr.name+' '+tr.attrs.class" :style="tr.attrs.style">
							<view v-for="(td, z) in tr.children" v-bind:key="z" :class="'_'+td.name+' '+td.attrs.class"
								:style="td.attrs.style">
								<node :childs="td.children" :opts="opts" />
							</view>
						</view>
					</block>
				</view>
			</view>
			<my-audio v-else-if="n.name=='audio'" :class="n.attrs.class" :style="n.attrs.style" :aid="n.attrs.id"
				:author="n.attrs.author" :controls="n.attrs.controls" :autoplay="n.attrs.autoplay" :loop="n.attrs.loop"
				:name="n.attrs.name" :poster="n.attrs.poster" :src="n.src[ctrl[i]||0]" :data-i="i" data-source="audio"
				@play="play" @error="mediaError" />
			<rich-text v-else-if="n.attrs['data-content']" :nodes="[n]" :data-content="n.attrs['data-content']"
				:data-lang="n.attrs['data-lang']" @longpress="copyCode" />
			<ad v-else-if="n.name=='ad'" :class="n.attrs.class" style="n.attrs.style" :unit-id="n.attrs['unit-id']"
				:appid="n.attrs.appid" :apid="n.attrs.apid" :data-i="i" @error="mediaError" />
			<!-- 富文本 -->
			<!-- #ifdef H5 || MP-WEIXIN || MP-QQ || APP-PLUS || MP-360 -->
			<rich-text v-else-if="handler.use(n)" :id="n.attrs.id" :style="n.f" :nodes="[n]"  />
			<!-- #endif -->
			<!-- #ifndef H5 || MP-WEIXIN || MP-QQ || APP-PLUS || MP-360 -->
			<rich-text v-else-if="!n.c" :id="n.attrs.id" :style="n.f+';display:inline'" :preview="false" :nodes="[n]" />
			<!-- #endif -->
			<!-- 继续递归 -->
			<view v-else-if="n.c===2" :id="n.attrs.id" :class="'_'+n.name+' '+n.attrs.class"
				:style="n.f+';'+n.attrs.style">
				<node v-for="(n2, j) in n.children" v-bind:key="j" :style="n2.f" :name="n2.name" :attrs="n2.attrs"
					:childs="n2.children" :opts="opts" />
			</view>
			<node v-else :style="n.f" :name="n.name" :attrs="n.attrs" :childs="n.children" :opts="opts" :class="n.name" />
		</block>
	</view>
</template>
<script module="handler" lang="wxs">
	// 行内标签列表
	var inlineTags = {
		abbr: true,
		b: true,
		big: true,
		code: true,
		del: true,
		em: true,
		i: true,
		ins: true,
		label: true,
		q: true,
		small: true,
		span: true,
		strong: true,
		sub: true,
		sup: true
	}
	/**
	 * @description 是否使用 rich-text 显示剩余内容
	 */
	module.exports = {
		use: function(item) {
			if (item.c) return false
			// 微信和 QQ 的 rich-text inline 布局无效
			return !inlineTags[item.name] && (item.attrs.style || '').indexOf('display:inline') == -1
		}
	}
</script>
<script>
	import myAudio from '../audio/audio'

	import node from './node'
	export default {
		name: 'node',
		options: {
			// #ifdef MP-WEIXIN
			virtualHost: true,
			// #endif
			// #ifdef MP-TOUTIAO
			addGlobalClass: false
			// #endif
		},
		data() {
			return {
				ctrl: {}
			}
		},
		props: {
			name: String,
			attrs: {
				type: Object,
				default () {
					return {}
				}
			},
			childs: Array,
			opts: Array
		},
		components: {
			myAudio,

			node
		},
		mounted() {
			this.$nextTick(() => {
				for (this.root = this.$parent; this.root.$options.name !== 'mp-html'; this.root = this.root
					.$parent);
			})
			// #ifdef H5 || APP-PLUS
			if (this.opts[0]) {
				let i
				for (i = this.childs.length; i--;) {
					if (this.childs[i].name === 'img') break
				}
				if (i !== -1) {
					this.observer = uni.createIntersectionObserver(this).relativeToViewport({
						top: 500,
						bottom: 500
					})
					this.observer.observe('._img', res => {
						if (res.intersectionRatio) {
							this.$set(this.ctrl, 'load', 1)
							this.observer.disconnect()
						}
					})
				}
			}
			// #endif
		},
		beforeDestroy() {
			// #ifdef H5 || APP-PLUS
			if (this.observer) {
				this.observer.disconnect()
			}
			// #endif
		},
		methods: {
			copyCode(e) {
				uni.showActionSheet({
					itemList: ['复制代码'],
					success: () =>
						uni.setClipboardData({
							data: e.currentTarget.dataset.content
						})
				})
			},
			// #ifdef MP-WEIXIN
			toJSON() {},
			// #endif
			/**
			 * @description 播放视频事件
			 * @param {Event} e
			 */
			play(e) {
				// #ifndef APP-PLUS
				if (this.root.pauseVideo) {
					let flag = false;
					const id = e.target.id
					for (let i = this.root._videos.length; i--;) {
						if (this.root._videos[i].id === id) {
							flag = true
						} else {
							this.root._videos[i].pause() // 自动暂停其他视频
						}
					}
					// 将自己加入列表
					if (!flag) {
						const ctx = uni.createVideoContext(id
							// #ifndef MP-BAIDU
							, this
							// #endif
						)
						ctx.id = id
						this.root._videos.push(ctx)
					}
				}
				// #endif
			},

			/**
			 * @description 图片点击事件
			 * @param {Event} e
			 */
			imgTap(e) {
				const node = this.childs[e.currentTarget.dataset.i]
				if (node.a) {
					this.linkTap(node.a)
					return
				}
				if (node.attrs.ignore) return
				// #ifdef H5 || APP-PLUS
				node.attrs.src = node.attrs.src || node.attrs['data-src']
				// #endif
				this.root.$emit('imgtap', node.attrs)
				// 自动预览图片
				if (this.root.previewImg) {
					uni.previewImage({
						current: parseInt(node.attrs.i),
						urls: this.root.imgList
					})
				}
			},

			/**
			 * @description 图片长按
			 */
			imgLongTap(e) {
				// #ifdef APP-PLUS
				const attrs = this.childs[e.currentTarget.dataset.i].attrs
				if (this.opts[3] && !attrs.ignore) {
					uni.showActionSheet({
						itemList: ['保存图片'],
						success: () => {
							const save = path => {
								uni.saveImageToPhotosAlbum({
									filePath: path,
									success() {
										uni.showToast({
											title: '保存成功'
										})
									}
								})
							}
							if (this.root.imgList[attrs.i].startsWith('http')) {
								uni.downloadFile({
									url: this.root.imgList[attrs.i],
									success: res => save(res.tempFilePath)
								})
							} else {
								save(this.root.imgList[attrs.i])
							}
						}
					})
				}
				// #endif
			},

			/**
			 * @description 图片加载完成事件
			 * @param {Event} e
			 */
			imgLoad(e) {
				const i = e.currentTarget.dataset.i
				/* #ifndef H5 || APP-PLUS */
				if (!this.childs[i].w) {
					// 设置原宽度
					this.$set(this.ctrl, i, e.detail.width)
				} else /* #endif */
					if ((this.opts[1] && !this.ctrl[i]) || this.ctrl[i] === -1) {
						// 加载完毕，取消加载中占位图
						this.$set(this.ctrl, i, 1)
					}
			},

			/**
			 * @description 链接点击事件
			 * @param {Event} e
			 */
			linkTap(e) {
				const node = e.currentTarget ? this.childs[e.currentTarget.dataset.i] : {}
				const attrs = node.attrs || e
				const href = attrs.href
				this.root.$emit('linktap', Object.assign({
					innerText: this.root.getText(node.children || []) // 链接内的文本内容
				}, attrs))
				if (href) {
					if (href[0] === '#') {
						// 跳转锚点
						this.root.navigateTo(href.substring(1)).catch(() => {})
					} else if (href.includes('://')) {
						// 复制外部链接
						if (this.root.copyLink) {
							// #ifdef H5
							window.open(href)
							// #endif
							// #ifdef MP
							uni.setClipboardData({
								data: href,
								success: () =>
									uni.showToast({
										title: '链接已复制'
									})
							})
							// #endif
							// #ifdef APP-PLUS
							plus.runtime.openWeb(href)
							// #endif
						}
					} else {
						// 跳转页面
						uni.navigateTo({
							url: href,
							fail() {
								uni.switchTab({
									url: href,
									fail() {}
								})
							}
						})
					}
				}
			},

			/**
			 * @description 错误事件
			 * @param {Event} e
			 */
			mediaError(e) {
				const i = e.currentTarget.dataset.i
				const node = this.childs[i]
				// 加载其他源
				if (node.name === 'video' || node.name === 'audio') {
					let index = (this.ctrl[i] || 0) + 1
					if (index > node.src.length) {
						index = 0
					}
					if (index < node.src.length) {
						this.$set(this.ctrl, i, index)
						return
					}
				} else if (node.name === 'img' && this.opts[2]) {
					// 显示错误占位图
					this.$set(this.ctrl, i, -1)
				}
				if (this.root) {
					this.root.$emit('error', {
						source: node.name,
						attrs: node.attrs,
						errMsg: e.detail.errMsg
					})
				}
			}
		}
	}
</script>
<style>
	@import url("@/components/fengrui.css");
	/deep/ .hl-code,
	/deep/ .hl-pre {
		color: #ccc;
		background: 0 0;
		font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
		font-size: 1em;
		text-align: left;
		white-space: pre;
		word-spacing: normal;
		word-break: normal;
		word-wrap: normal;
		line-height: 1.5;
		-moz-tab-size: 4;
		-o-tab-size: 4;
		tab-size: 4;
		-webkit-hyphens: none;
		-moz-hyphens: none;
		-ms-hyphens: none;
		hyphens: none;
		/* border-radius: 20upx; */
	}

	/deep/ .hl-pre {
		padding: 1em;
		margin: .5em 0;
		overflow: auto
	}

	/deep/ .hl-pre {
		background: #2d2d2d
	}

	/deep/ .hl-block-comment,
	/deep/ .hl-cdata,
	/deep/ .hl-comment,
	/deep/ .hl-doctype,
	/deep/ .hl-prolog {
		color: #999
	}

	/deep/ .hl-punctuation {
		color: #ccc
	}

	/deep/ .hl-attr-name,
	/deep/ .hl-deleted,
	/deep/ .hl-namespace,
	/deep/ .hl-tag {
		color: #e2777a
	}

	/deep/ .hl-function-name {
		color: #6196cc
	}

	/deep/ .hl-boolean,
	/deep/ .hl-function,
	/deep/ .hl-number {
		color: #f08d49
	}

	/deep/ .hl-class-name,
	/deep/ .hl-constant,
	/deep/ .hl-property,
	/deep/ .hl-symbol {
		color: #f8c555
	}

	/deep/ .hl-atrule,
	/deep/ .hl-builtin,
	/deep/ .hl-important,
	/deep/ .hl-keyword,
	/deep/ .hl-selector {
		color: #cc99cd
	}

	/deep/ .hl-attr-value,
	/deep/ .hl-char,
	/deep/ .hl-regex,
	/deep/ .hl-string,
	/deep/ .hl-variable {
		color: #7ec699
	}

	/deep/ .hl-entity,
	/deep/ .hl-operator,
	/deep/ .hl-url {
		color: #67cdcc
	}

	/deep/ .hl-bold,
	/deep/ .hl-important {
		font-weight: 700
	}

	/deep/ .hl-italic {
		font-style: italic
	}

	/deep/ .hl-entity {
		cursor: help
	}

	/deep/ .hl-inserted {
		color: green
	}

	/deep/ .md-p {
		margin-block-start: 1em;
		margin-block-end: 1em;
	}

	/deep/ .md-table,
	/deep/ .md-blockquote {
		margin-bottom: 16px;
	}

	/deep/ .md-table {
		box-sizing: border-box;
		width: 100%;
		overflow: auto;
		border-spacing: 0;
		border-collapse: collapse;
	}

	/deep/ .md-tr {
		background-color: #fff;
		border-top: 1px solid #c6cbd1;
	}

	/deep/ .md-table .md-tr:nth-child(2n) {
		background-color: #f6f8fa;
	}

	/deep/ .md-th,
	/deep/ .md-td {
		padding: 6px 13px !important;
		border: 1px solid #dfe2e5;
	}

	/deep/ .md-th {
		font-weight: 600;
	}

	/deep/ .md-blockquote {
		padding: 0 1em;
		color: #6a737d;
		border-left: 0.25em solid #dfe2e5;
	}

	/deep/ .md-code {
		padding: 0.2em 0.4em;
		font-family: SFMono-Regular, Consolas, Liberation Mono, Menlo, monospace;
		font-size: 85%;
		background-color: rgba(27, 31, 35, 0.05);
		border-radius: 3px;
	}

	/deep/ .md-pre .md-code {
		padding: 0;
		font-size: 100%;
		background: transparent;
		border: 0;
	}

	/deep/ .hl-pre {
		position: relative;
	}

	/deep/ .hl-code {
		overflow: auto;
		display: block;
	}

	/deep/ .hl-language {
		font-size: 12px;
		font-weight: 600;
		position: absolute;
		right: 8px;
		text-align: right;
		top: 3px;
	}

	/deep/ .hl-pre {
		padding-top: 1.5em;
	}

	/deep/ .hl-pre {
		font-size: 14px;
		padding-left: 3.8em;
		counter-reset: linenumber;
	}

	/deep/ .line-numbers-rows {
		position: absolute;
		pointer-events: none;
		top: 1.5em;
		font-size: 100%;
		left: 0;
		width: 3em;
		/* works for line-numbers below 1000 lines */
		letter-spacing: -1px;
		border-right: 1px solid #999;
		-webkit-user-select: none;
		-moz-user-select: none;
		-ms-user-select: none;
		user-select: none;
	}

	/deep/ .line-numbers-rows .span {
		display: block;
		counter-increment: linenumber;
	}

	/deep/ .line-numbers-rows .span:before {
		content: counter(linenumber);
		color: #999;
		display: block;
		padding-right: 0.8em;
		text-align: right;
	}

	/* a 标签默认效果 */
	._a {
		padding: 1.5px 0 1.5px 0;
		color: #366092;
		word-break: break-all;
	}

	/* a 标签点击态效果 */
	._hover {
		text-decoration: underline;
		opacity: 0.7;
	}

	/* 图片默认效果 */
	._img {
		max-width: 100%;
		-webkit-touch-callout: none;
	}

	/* 内部样式 */

	._b,
	._strong {
		font-weight: bold;
	}

	._code {
		font-family: monospace;
	}

	._del {
		text-decoration: line-through;
	}

	._em,
	._i {
		font-style: italic;
	}

	._h1 {
		font-size: 2em;
	}

	._h2 {
		font-size: 1.5em;
	}

	._h3 {
		font-size: 1.17em;
	}

	._h5 {
		font-size: 0.83em;
	}

	._h6 {
		font-size: 0.67em;
	}

	._h1,
	._h2,
	._h3,
	._h4,
	._h5,
	._h6 {
		display: block;
		font-weight: bold;
	}

	._image {
		height: 1px;
	}

	._ins {
		text-decoration: underline;
	}

	._li {
		display: list-item;
	}

	._ol {
		list-style-type: decimal;
	}

	._ol,
	._ul {
		display: block;
		padding-left: 40px;
		margin: 1em 0;
	}

	._q::before {
		content: '"';
	}

	._q::after {
		content: '"';
	}

	._sub {
		font-size: smaller;
		vertical-align: sub;
	}

	._sup {
		font-size: smaller;
		vertical-align: super;
	}

	._thead,
	._tbody,
	._tfoot {
		display: table-row-group;
	}

	._tr {
		display: table-row;
	}

	._td,
	._th {
		display: table-cell;
		vertical-align: middle;
	}

	._th {
		font-weight: bold;
		text-align: center;
	}

	._ul {
		list-style-type: disc;
	}

	._ul ._ul {
		margin: 0;
		list-style-type: circle;
	}

	._ul ._ul ._ul {
		list-style-type: square;
	}

	._abbr,
	._b,
	._code,
	._del,
	._em,
	._i,
	._ins,
	._label,
	._q,
	._span,
	._strong,
	._sub,
	._sup {
		display: inline;
	}

	/* #ifdef APP-PLUS */
	._video {
		width: 300px;
		height: 225px;
	}

	/* #endif */
</style>
